package cn.jdemo.base.clazz;

import org.openjdk.jol.info.ClassLayout;

/**
 * Java对象头一般占有2个机器码（64位虚拟机中，1个机器码是8个字节，也就是64bit），
 * 但是 如果对象是数组类型，则需要3个机器码
 *
 * 1)Java对象的元数据信息可确定Java对象的大小
 * 2)但是无法从数组的元数据来确认数组的大小
 *
 * markword = 4 + 4 = 8字节
 * 引用类型从8字节压缩后为4字节
 * 数组长度从8字节压缩后为4字节
 */
public class Demojol {
    public static void main(String[] args) {
        // test01();// Clazz.class
        // test02();// Clazz.instance
        // test03();// Clazz2.instance
        // test04(); // Clazz2.instance + 禁用指针压缩 -XX:-UseCompressedOops
        // test05();// // Clazz3.instance
        // test06();// // Clazz3.instance + 禁用指针压缩 -XX:-UseCompressedOops
        test07();
    }

    /**
     *  输出:
     *  cn.jdemo.base.clazz.Clazz object internals:
     *  OFFSET  SIZE                TYPE DESCRIPTION                               VALUE
     *       0    12                     (object header)                           N/A
     *      12     4                 int Clazz.a                                   N/A
     *      16     4   java.lang.Integer Clazz.b                                   N/A
     *      20     4               int[] Clazz.c                                   N/A
     *      24     4              long[] Clazz.d                                   N/A
     *      28     4                     (loss due to the next object alignment)
     * Instance size: 32 bytes
     * Space losses: 0 bytes internal + 4 bytes external = 4 bytes total
     *
     * 1)java数组长度最大是Integer.MAX_VALUE;
     * 2)int Integer在class对象中都是4Byte;
     */
    private static void test01() {
        String printable = ClassLayout.parseClass(Clazz.class).toPrintable();
        System.out.println(printable);
    }

    /**
     * 输出:
     * cn.jdemo.base.clazz.Clazz object internals:
     *  OFFSET  SIZE                TYPE DESCRIPTION                               VALUE
     *       0     4                     (object header)                           01 00 00 00 (00000001 00000000 00000000 00000000) (1)
     *       4     4                     (object header)                           00 00 00 00 (00000000 00000000 00000000 00000000) (0)
     *       8     4                     (object header)                           43 c0 00 f8 (01000011 11000000 00000000 11111000) (-134168509)
     *      12     4                 int Clazz.a                                   0
     *      16     4   java.lang.Integer Clazz.b                                   null
     *      20     4               int[] Clazz.c                                   [0,... ...0, 0, 0, 0, 0]
     *      24     4              long[] Clazz.d                                   [0,... ...0, 0, 0, 0, 0]
     *      28     4                     (loss due to the next object alignment)
     * Instance size: 32 bytes
     * Space losses: 0 bytes internal + 4 bytes external = 4 bytes total
     *
     */
    private static void test02() {
        String printable = ClassLayout.parseInstance(new Clazz()).toPrintable();
        System.out.println(printable);
    }

    /**
     * 输出:
     * cn.jdemo.base.clazz.Clazz2 object internals:
     *  OFFSET  SIZE               TYPE DESCRIPTION                               VALUE
     *       0     4                    (object header)                           01 00 00 00 (00000001 00000000 00000000 00000000) (1)
     *       4     4                    (object header)                           00 00 00 00 (00000000 00000000 00000000 00000000) (0)
     *       8     4                    (object header)                           43 c0 00 f8 (01000011 11000000 00000000 11111000) (-134168509)
     *      12     4              int[] Clazz2.e                                  [1, 2, 3, 4, 5, 6, 7, 8]
     *      16     4   java.lang.String Clazz2.f                                  (object)
     *      20     4                    (loss due to the next object alignment)
     * Instance size: 24 bytes
     * Space losses: 0 bytes internal + 4 bytes external = 4 bytes total
     */
    private static void test03() {
        String printable = ClassLayout.parseInstance(new Clazz2()).toPrintable();
        System.out.println(printable);
    }

    /**
     * 没有指针压缩：对象头8+8,数组引用8,字符串引用8
     * cn.jdemo.base.clazz.Clazz2 object internals:
     *  OFFSET  SIZE               TYPE DESCRIPTION                               VALUE
     *       0     4                    (object header)                           01 00 00 00 (00000001 00000000 00000000 00000000) (1)
     *       4     4                    (object header)                           00 00 00 00 (00000000 00000000 00000000 00000000) (0)
     *       8     4                    (object header)                           f8 0d ff 1b (11111000 00001101 11111111 00011011) (469700088)
     *      12     4                    (object header)                           00 00 00 00 (00000000 00000000 00000000 00000000) (0)
     *      16     8              int[] Clazz2.e                                  [1, 2, 3, 4, 5, 6, 7, 8]
     *      24     8   java.lang.String Clazz2.f                                  (object)
     * Instance size: 32 bytes
     * Space losses: 0 bytes internal + 0 bytes external = 0 bytes total
     */
    private static void test04() {
        String printable = ClassLayout.parseInstance(new Clazz2()).toPrintable();
        System.out.println(printable);
    }

    /**
     * 指针压缩:对象头8+4,其中markwords是8字节,其中指向class得4字节
     * cn.jdemo.base.clazz.Clazz3 object internals:
     *  OFFSET  SIZE                        TYPE DESCRIPTION                               VALUE
     *       0     4                             (object header)                           01 00 00 00 (00000001 00000000 00000000 00000000) (1)
     *       4     4                             (object header)                           00 00 00 00 (00000000 00000000 00000000 00000000) (0)
     *       8     4                             (object header)                           43 c0 00 f8 (01000011 11000000 00000000 11111000) (-134168509)
     *      12     2                        char Clazz3.j                                  a
     *      14     1                     boolean Clazz3.k                                  false
     *      15     1                        byte Clazz3.l                                  10
     *      16     8                        long Clazz3.h                                  1024
     *      24     4                      long[] Clazz3.i                                  [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
     *      28     4                      long[] Clazz3.m                                  [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 13]
     *      32     4   cn.jdemo.base.clazz.Clazz Clazz3.clazz                              null
     *      36     4   cn.jdemo.base.clazz.Clazz Clazz3.clazz2                             (object)
     *
     * @see Demojol#test06() 没有指针压缩
     */
    private static void test05() {
        String printable = ClassLayout.parseInstance(new Clazz3()).toPrintable();
        System.out.println(printable);
    }

    /**
     * 没有指针压缩：对象头8+8,其中markwords是8字节,其中指向class引用8字节
     * cn.jdemo.base.clazz.Clazz3 object internals:
     *  OFFSET  SIZE                        TYPE DESCRIPTION                               VALUE
     *       0     4                             (object header)                           01 00 00 00 (00000001 00000000 00000000 00000000) (1)
     *       4     4                             (object header)                           00 00 00 00 (00000000 00000000 00000000 00000000) (0)
     *       8     4                             (object header)                           50 11 08 1c (01010000 00010001 00001000 00011100) (470290768)
     *      12     4                             (object header)                           00 00 00 00 (00000000 00000000 00000000 00000000) (0)
     *      16     8                        long Clazz3.h                                  1024
     *      24     2                        char Clazz3.j                                  a
     *      26     1                     boolean Clazz3.k                                  false
     *      27     1                        byte Clazz3.l                                  10
     *      28     4                             (alignment/padding gap)内存对齐
     *      32     8                      long[] Clazz3.i                                  [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
     *      40     8                      long[] Clazz3.m                                  [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 13]
     *      48     8   cn.jdemo.base.clazz.Clazz Clazz3.clazz                              null
     *      56     8   cn.jdemo.base.clazz.Clazz Clazz3.clazz2                             (object)
     * Instance size: 64 bytes
     * Space losses: 4 bytes internal + 0 bytes external = 4 bytes total
     *
     * @see Demojol#test05() 指针压缩
     */
    private static void test06() {
        String printable = ClassLayout.parseInstance(new Clazz3()).toPrintable();
        System.out.println(printable);
    }

    /**
     * 指针压缩得:对象头中,markword=4+4,指向class得引用4,数组大小4
     * [Lcn.jdemo.base.clazz.Clazz3; object internals:
     *  OFFSET  SIZE                         TYPE DESCRIPTION                               VALUE
     *       0     4                              (object header)                           01 00 00 00 (00000001 00000000 00000000 00000000) (1)
     *       4     4                              (object header)                           00 00 00 00 (00000000 00000000 00000000 00000000) (0)
     *       8     4                              (object header)                           82 c0 00 f8 (10000010 11000000 00000000 11111000) (-134168446)
     *      12     4                              (object header)                           02 00 00 00 (00000010 00000000 00000000 00000000) (1024)
     *      16  4096   cn.jdemo.base.clazz.Clazz3 Clazz3;.<elements>                        N/A
     */
    private static void test07() {
        Clazz3[] clazz3 = new Clazz3[2];
        String printable = ClassLayout.parseInstance(clazz3).toPrintable();
        System.out.println(printable);
    }
}
